package com.ny.service.impl;

import com.ny.entity.User;
import com.ny.mapper.UserMapper;

import com.ny.service.EmailService;
import com.ny.service.UserService;

import com.ny.util.VerificationCodeUtil;
import io.jsonwebtoken.lang.Assert;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;
    // 注入邮件服务
    @Autowired
    private EmailService emailService;

    // 注入Redis模板（存储验证码）
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 从配置文件读取验证码配置
    @Value("${reset.code.expire}")
    private int codeExpireTime; // 验证码有效期（秒）

    @Value("${reset.code.length}")
    private int codeLength; // 验证码长度

    // 原有方法...
    @Override
    public List<User> findAll() {
        return userMapper.findAll();
    }

    @Override
    public User findUserByNickName(String nickname) {
        return userMapper.findUserByNackName(nickname);
    }

    @Override
    public void register(User user) {
        int usernameCount = userMapper.countByUsername(user.getUsername());
        Assert.isTrue(usernameCount == 0, "用户名已被注册，请更换其他用户名");

        String encryptedPassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encryptedPassword);

        user.setIs_active(1);
        user.setCreated_time(new Date());

        int insertRows = userMapper.insertUser(user);
        Assert.isTrue(insertRows > 0, "注册失败，请稍后重试");
    }

    @Override
    public User findUserByUsername(String username) {
        return userMapper.findUserByUsername(username);
    }

    @Override
    public boolean checkLogin(String username, String rawPassword) {
        User user = userMapper.findUserByUsername(username);
        if (user == null) {
            return false;
        }
        return passwordEncoder.matches(rawPassword, user.getPassword());
    }

    /**
     * 发送密码重置验证码（业务逻辑）
     */
    @Override
    public void sendResetCode(String email) {
        // 1. 校验邮箱是否为空
        Assert.isTrue(StringUtils.hasText(email), "邮箱不能为空");

        // 2. 校验邮箱对应的用户是否存在
        User user = userMapper.findUserByEmail(email);
        Assert.notNull(user, "该邮箱未注册，请核对后重试");

        // 3. 生成验证码
        String code = VerificationCodeUtil.generateCode(codeLength);

        // 4. 存储验证码到Redis（key：reset_password:email:xxx，value：验证码，过期时间：codeExpireTime秒）
        String redisKey = "reset_password:email:" + email;
        stringRedisTemplate.opsForValue().set(redisKey, code, codeExpireTime, TimeUnit.SECONDS);

        // 5. 发送验证码邮件
        emailService.sendResetCodeEmail(email, code, codeExpireTime);
    }

    /**
     * 验证验证码并重置密码（业务逻辑）
     */
    @Override
    public void resetPassword(String email, String code, String newPassword) {
        // 1. 基础参数校验
        Assert.isTrue(StringUtils.hasText(email), "邮箱不能为空");
        Assert.isTrue(StringUtils.hasText(code), "验证码不能为空");
        Assert.isTrue(StringUtils.hasText(newPassword), "新密码不能为空");
        // 校验新密码长度（6-20位）
        Assert.isTrue(newPassword.length() >= 6 && newPassword.length() <= 20, "新密码长度需在6-20位之间");

        // 2. 校验邮箱对应的用户是否存在
        User user = userMapper.findUserByEmail(email);
        Assert.notNull(user, "该邮箱未注册，请核对后重试");

        // 3. 从Redis获取存储的验证码
        String redisKey = "reset_password:email:" + email;
        String storedCode = stringRedisTemplate.opsForValue().get(redisKey);

        // 4. 校验验证码（是否存在/是否匹配）
        Assert.notNull(storedCode, "验证码已过期，请重新获取");
        Assert.isTrue(storedCode.equals(code), "验证码错误，请重新输入");

        // 5. 加密新密码（与注册时加密方式一致）
        String encryptedNewPassword = passwordEncoder.encode(newPassword);

        // 6. 更新数据库中的密码
        int updateRows = userMapper.updatePasswordByEmail(email, encryptedNewPassword);
        Assert.isTrue(updateRows > 0, "密码重置失败，请稍后重试");

        // 7. 重置成功后，删除Redis中的验证码（避免重复使用）
        stringRedisTemplate.delete(redisKey);
    }


}